package com.btcTool;

import org.bitcoinj.core.Base58;
import org.bitcoinj.core.ECKey;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static com.btcTool.KeyFormat.PRIV_KEY_WIF;
import static org.bitcoinj.core.Utils.sha256hash160;

/**
 * base58check 编码
 * @author 160516a
 *
 */
public class BtcUtils {

    /**
     * base58check编码
     * 第一位 version
     * 中间32位：数据
     * 后四位 ： 校验码
     * @param version
     * @param input
     * @return
     */
    public static String encode (byte version, byte[] input) {
        byte[] versionInput = new byte[ 1 + input.length];
        //版本
        versionInput[0] = version;
        System.arraycopy(input, 0, versionInput, 1, input.length);
        byte[] checkByte = doubleSha256(versionInput);
        byte[] checkInputData = new byte[ 1 + input.length + 4];
        System.arraycopy(versionInput, 0, checkInputData, 0, versionInput.length);
        //检验字节
        System.arraycopy(checkByte, 0, checkInputData, versionInput.length, 4);
        return Base58.encode(checkInputData);
    }

    /**
     * base58check解码
     * @param input
     * @return
     */
    public static byte[] decode (String input) {
        byte[] rawByte = Base58.decode(input);
        byte[] result = new byte[ rawByte.length -1 -4];
        System.arraycopy(rawByte, 1, result, 0, result.length);
        return result;
    }
    /**
     * 执行2次sha256加密算法，截取结果的前4个字节作为checknum，加到btc地址中
     * @param input
     * @return
     */
    private static byte[] doubleSha256 (byte[] input) {
        try {
            byte[] sha256 = MessageDigest.getInstance("SHA-256").digest(input);
            return MessageDigest.getInstance("SHA-256").digest(sha256);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e); // Cannot happen.
        }
    }
    public static String toHexString(byte[] b) {
        String str = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            str += hex.toUpperCase();
        }
        return str;
    }

    public static byte[] hexStringToByte(String hexString) {
        int length = hexString.length();
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return bytes;
    }

    public static String getBtcAddress (byte[] pubKeyBytes) {

        byte[] hash160 = sha256hash160(pubKeyBytes);

        byte version = 0x00;

        return encode(version, hash160);

    }

    public static BigInteger byte32toBigInteger (byte[] byte32) {
        if ( byte32 == null ||
                byte32.length != 32 )
            throw new BtcException("输入字节数字位数不等于32");
        //注意，数字为正数
        return new BigInteger(1, byte32);
    }

    public static String getPrivateKeyStr(){
        ECKey ecKey = new ECKey();
        PrivateKeyFormat privateKeyFormat = new PrivateKeyFormat(PRIV_KEY_WIF);
        String privateKey = privateKeyFormat.format(ecKey.getPrivKeyBytes());
       // System.out.println(privateKey);
        return privateKey;
    }

    public static String getBtcAddress(String privateKeyStr){
        PrivateKeyFormat privateKeyFormat = new PrivateKeyFormat(PRIV_KEY_WIF);
        byte[] privKeyBytes = privateKeyFormat.parse(privateKeyStr);
        byte[] pubKeyBytes = ECKey.publicKeyFromPrivate(BtcUtils.byte32toBigInteger(privKeyBytes), false);
        String address = BtcUtils.getBtcAddress(pubKeyBytes);
       // System.out.println(address);
        return address;
    }

}
